package org.com.lcuiot.security;

import com.google.gson.Gson;
import org.com.lcuiot.database.dto.Result;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.*;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * web详细配置
 *
 * @author gaoge
 * @since 2022/10/27 15:29
 */
@Configuration
public class SecurityConfig {

    @Resource
    private AuthenticationFailureHandler authenticationFailureHandler;

    private final Gson gson =new Gson();


    @Bean
    SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http,
                                                JwtTokenProvider tokenProvider,
                                                ReactiveAuthenticationManager reactiveAuthenticationManager) {

        return http
                .csrf(ServerHttpSecurity.CsrfSpec::disable)
                .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
                .formLogin()
                .authenticationFailureHandler(authenticationFailureHandler)
                .and()
                .authenticationManager(reactiveAuthenticationManager)
                .exceptionHandling().authenticationEntryPoint(
                        (swe, e) -> {
                            swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                            return swe.getResponse().writeWith(Mono.just(new DefaultDataBufferFactory().wrap(gson.toJson(Result.build().setCode(500).setMsg("Token认证信息失效，请重新登陆")).getBytes())));
                        })
                .accessDeniedHandler((swe, e) -> {
                    swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                    return swe.getResponse().writeWith(Mono.just(new DefaultDataBufferFactory().wrap(gson.toJson(Result.build().setCode(500).setMsg("权限不足")).getBytes())));
                })
                .and()

                .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
                .authorizeExchange(it -> it
                        .pathMatchers("/auth/**","/accept_data").permitAll()
//                        .pathMatchers(HttpMethod.POST, "/auth/register").permitAll()
//                        .pathMatchers(HttpMethod.POST, "/auth/login").permitAll()
//                        .pathMatchers(HttpMethod.GET, "/admin").hasRole("ADMIN")
//                        .pathMatchers(HttpMethod.GET, "/user").hasRole("USER")
                        .anyExchange().authenticated()

                )
                .addFilterAt(new JwtTokenAuthenticationFilter(tokenProvider), SecurityWebFiltersOrder.HTTP_BASIC)
                .build();
    }



    @Bean
    public ReactiveAuthenticationManager reactiveAuthenticationManager(CustomUserDetailsService userDetailsService,
                                                                       PasswordEncoder passwordEncoder) {
        UserDetailsRepositoryReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
        authenticationManager.setPasswordEncoder(passwordEncoder);
        return authenticationManager;
    }



}
